package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.Constants;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.CommentApi;
import com.tanhua.dubbo.api.mongo.MovementApi;
import com.tanhua.dubbo.api.mongo.VisitorApi;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.*;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.collections.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MovementService {

    @DubboReference
    private MovementApi movementApi;
    @Autowired
    private OssTemplate ossTemplate;
    @DubboReference
    private UserInfoApi userInfoApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @DubboReference
    private CommentApi commentApi;
    @DubboReference
    private VisitorApi visitorApi;
    @Autowired
    private UserFreezeService userFreezeService;
    @Autowired
    private MqMessageService mqMessageService;

    /**
     * 发布动态
     * @param movementVo
     * @param imageContent
     */
    public void postMovements(MovementVo movementVo, MultipartFile[] imageContent) {
        Long userId = UserHolder.getUserId();
        //判断是否被限制发布动态
        userFreezeService.checkUserStates(userId, Constants.USER_FREEZE_MOVEMENT);

        if (StringUtils.isEmpty(movementVo.getTextContent())) {
            throw new TanHuaException(ErrorResult.emptyContextCodeError());
        }
        List<String> medias = new ArrayList<>();
        //上传图片
        try {
            for (MultipartFile multipartFile : imageContent) {
                String originalFilename = multipartFile.getOriginalFilename();
                medias.add(ossTemplate.upload(originalFilename, multipartFile.getInputStream()));
            }
        } catch (IOException e) {
            throw new TanHuaException(ErrorResult.error());
        }

        Movement movement = new Movement();
        movement.setMedias(medias);
        BeanUtils.copyProperties(movementVo, movement);
        movement.setLocationName(movementVo.getLocation());
        movement.setUserId(userId);
        movement.setId(new ObjectId());

        movementApi.publish(movement);
        mqMessageService.sendLogMessage(userId, "0201", "movement", movement.getId().toHexString());
        mqMessageService.sendAudiMessage(movement.getId().toHexString());
    }

    /**
     * 根据用户id查询动态
     * @param page
     * @param pageSize
     * @param userId
     * @return
     */
    public PageResult<MovementsVo> findByUserId(Long page, Long pageSize, Long userId) {
        PageResult<Movement> pageResult= movementApi.findByUserId(page, pageSize, userId);
        List<Movement> movements = pageResult.getItems();
        List<MovementsVo> voList = new ArrayList<>();

        if(CollectionUtils.isNotEmpty(movements)) {
            List<ObjectId> movementIds = movements.stream().map(Movement::getId).collect(Collectors.toList());
            Long visitorId = UserHolder.getUserId();
            Map<ObjectId, Boolean> likeMap = commentApi.findLikeInMovements(visitorId, movementIds);
            Map<ObjectId, Boolean> loveMap = commentApi.findLoveInMovements(visitorId, movementIds);
            for (Movement movement : movements) {
                UserInfo userInfo = userInfoApi.getById(movement.getUserId());
                MovementsVo vo = MovementsVo.init(userInfo, movement);
                if(null != likeMap.get(movement.getId())) {
                    vo.setHasLiked(1);
                }
                if(null != loveMap.get(movement.getId())) {
                    vo.setHasLoved(1);
                }
                voList.add(vo);
            }
        }

        return new PageResult(page, pageSize, pageResult.getCounts(), voList);
    }

    /**
     * 查询好友动态
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult getFriendMovements(Long page, Long pageSize) {
        PageResult<Movement> pageResult = movementApi.getMovementsByFriendId(UserHolder.getUserId(), page, pageSize);
        List<Movement> movements = pageResult.getItems();
        List<MovementsVo> vos = convert2VO(movements);
        mqMessageService.sendLogMessage(UserHolder.getUserId(), "0202", "movement", UserHolder.getUserId().toString());
        return new PageResult(page, pageSize, pageResult.getCounts(), vos);
    }

    /**
     * 推荐动态
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult getRecommendMovements(Long page, Long pageSize) {
        String key = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId();
        String recommendMovementPid = redisTemplate.opsForValue().get(key);
        List<Movement> movements = new ArrayList();
        long total = 0L;

        if(StringUtils.isEmpty(recommendMovementPid)) {
            if(((page - 1) * pageSize) < 10) {
                //不推荐自己
                movements = movementApi.randomMovement(UserHolder.getUserId(), pageSize);
                total = pageSize;
            }
        }else {
            String[] pidArr = recommendMovementPid.split(",");
            long start = (page -1) * pageSize;
            total = pidArr.length;
            if(total > start) {
                List<Long> pidList = Arrays.stream(pidArr).skip(start).limit(pageSize)
                        .map(pid -> Long.valueOf(pid)).collect(Collectors.toList());
                movements = movementApi.getByPid(pidList);
            }
        }
        List<MovementsVo> vos = convert2VO(movements);
        return new PageResult(page, pageSize, total, vos);
    }

    /**
     * movementList转movementsVoList
     * @param movements
     * @return
     */
    private List<MovementsVo>  convert2VO(List<Movement> movements) {
        List<MovementsVo> vos = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(movements)) {
            List<Long> userIds = CollUtil.getFieldValues(movements, "userId", Long.class);
            Map<Long, UserInfo> userInfoMap = userInfoApi.getBatchIdsByCondition(userIds, null);
            List<ObjectId> movementIds = movements.stream().map(Movement::getId).collect(Collectors.toList());
            Map<ObjectId, Boolean> likeMap = commentApi.findLikeInMovements(UserHolder.getUserId(), movementIds);
            Map<ObjectId, Boolean> loveMap = commentApi.findLoveInMovements(UserHolder.getUserId(), movementIds);

            movements.forEach(movement -> {
                UserInfo userInfo = userInfoMap.get(movement.getUserId());
                if(null != userInfo) {
                    MovementsVo vo = MovementsVo.init(userInfo, movement);
                    if(null != likeMap.get(movement.getId())) {
                        vo.setHasLiked(1);
                    }
                    if(null != loveMap.get(movement.getId())) {
                        vo.setHasLoved(1);
                    }
                    vos.add(vo);
                }
            });
        }
        return vos;
    }

    /**
     * 根据id查询动态
     * @param id
     * @return
     */
    public MovementsVo getMovementById(String id) {
        Movement movement =  movementApi.getMovementById(id);
        UserInfo userInfo = userInfoApi.getById(movement.getUserId());
        return MovementsVo.init(userInfo, movement);
    }

    /**
     * 动态点赞
     * @param movementId
     */
    public Integer movementLike(String movementId) {
        Long userId = UserHolder.getUserId();
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(userId);

        Integer count = commentApi.publish(comment);
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key, hashKey, "1");
        mqMessageService.sendLogMessage(userId, "0203", "movement", movementId);
        return count;
    }

    /**
     * 取消喜欢
     * @param movementId
     * @return
     */
    public Integer movementDislike(String movementId) {
        Long userId = UserHolder.getUserId();
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(userId);

        Integer likeCount = commentApi.remove(comment);
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key, hashKey);
        mqMessageService.sendLogMessage(userId, "0206", "movement", movementId);
        return likeCount;
    }

    /**
     * 动态喜欢
     * @param movementId
     * @return
     */
    public Integer movementLove(String movementId) {
        Long userId = UserHolder.getUserId();
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(userId);
        Integer loveCount = commentApi.publish(comment);

        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key, hashKey, "1");
        mqMessageService.sendLogMessage(userId, "0204", "movement", movementId);

        return loveCount;
    }

    /**
     * 动态不喜欢
     * @param movementId
     * @return
     */
    public Integer movementUnlove(String movementId) {
        Long userId = UserHolder.getUserId();
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(userId);
        Integer loveCount = commentApi.remove(comment);

        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key, hashKey);
        mqMessageService.sendLogMessage(userId, "0207", "movement", movementId);
        return loveCount;
    }

    /**
     * 获取今日访客列表
     * @return
     */
    public List<VisitorsVo> findLast4Visitors() {
        List<VisitorsVo> result = new ArrayList<>();

        String key = Constants.VISITORS_USER;
        String hashKey = UserHolder.getUserId().toString();
        String lastTimeStr = (String)redisTemplate.opsForHash().get(key, hashKey);
        Long lastTime = null == lastTimeStr ? null : Long.valueOf(lastTimeStr);

        List<Visitors> visitorList = visitorApi.findLast4Visitors(UserHolder.getUserId(), lastTime);

        if(CollectionUtils.isNotEmpty(visitorList)) {
            List<Long> ids = visitorList.stream().map(Visitors::getVisitorUserId).collect(Collectors.toList());
            Map<Long, UserInfo> userInfoMap = userInfoApi.getBatchIdsByCondition(ids, null);
            visitorList.forEach(visitors -> {
                UserInfo userInfo = userInfoMap.get(visitors.getVisitorUserId());
                result.add(VisitorsVo.init(userInfo, visitors));
            });
        }

        return result;
    }
}
